﻿using Newtonsoft.Json;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using log4net;
using Ross.OA.Services;

namespace Ross.OA.Client
{
    public class Comms
    {
        public static string Company = "001";
        public static string CompanyName = "公司";
        public static string UserName = "";
        public static string Department = "";
        public static string DepartCode = "";
        public static string Powers = "";
        //public static string LogPath = Application.StartupPath + "\\log.txt";
        public static string LocalCfg = Application.StartupPath + "\\localcfg.json";
        public static readonly ILog log = LogManager.GetLogger("Logging");
        private SqlConnection conn;
        private CommDBService _service;
        public static Comms Instance
        {
            get
            {
                return new Comms();
            }
        }
        public Comms()
        {
            conn = new SqlConnection();
            _service = new CommDBService();
        }
        public static T D2E<T>(System.Windows.Forms.DataGridViewRow r)
        {
            T t = default(T);
            t = Activator.CreateInstance<T>();
            PropertyInfo[] ps = t.GetType().GetProperties();
            foreach (var item in ps)
            {
                if (r.DataGridView.Columns.Contains(item.Name))
                {
                    object v = r.Cells[item.Name];
                    if (v.GetType() == typeof(System.DBNull))
                        v = null;
                    item.SetValue(t, v, null);
                }
            }
            return t;
        }

        public void DgvCellPaste(string ColumnName, System.Windows.Forms.DataGridView dgv)
        {
            try
            {
                DataTable dt = new DataTable();
                dgv.DataSource = null;
                // 获取剪切板的内容，并按行分割
                string pasteText = System.Windows.Forms.Clipboard.GetText();
                if (string.IsNullOrEmpty(pasteText))
                    return;
                string[] lines = pasteText.Split('\n');
                //再按单元格填充行
                foreach (string line in lines)
                {
                    if (string.IsNullOrEmpty(line.Trim()))
                        continue;
                    // 按 Tab 分割数据
                    string[] vals = line.Split('\t');
                }
                dgv.DataSource = dt;
            }
            catch
            {
                // 不处理
            }
        }

        public static int DiffDay(DateTime sDate, DateTime eDate)
        {
            TimeSpan sp = eDate.Subtract(sDate);
            return sp.Days;
        }
        public bool CheckUpdate(string AutoUpdateURL)
        {
            bool result = false;
            try
            {
                string Cfg = TxtRead(AutoUpdateURL + "\\cfg.txt");
                int VersionRemote = int.Parse(Cfg.Replace(".", ""));
                int VersionLocal = int.Parse(System.Windows.Forms.Application.ProductVersion.Replace(".", ""));
                result = VersionRemote > VersionLocal;
            }
            catch { }
            return result;
        }
        /// <summary>
        /// 记录日志
        /// </summary>
        /// <param name="contents"></param>
        public static void Log(string contents)
        {
            try
            {
                //FileStream fs = new FileStream(LogPath, FileMode.Append);
                //StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
                //// 添加时间戳并换行，确保每条日志独立一行
                //sw.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {contents}");
                //sw.Flush();
                //sw.Close();
                //fs.Close();                
                log.Info(contents);
            }
            catch(Exception e) { }            
        }
        public static void DBLog(string apiName, DateTime askTime, string askContent, DateTime backTime, string backContent)
        {
            Instance._service.WriteLog(apiName, askTime, askContent, backTime, backContent);
        }
        public void TxtWrite(string path, string contents)
        {
            FileStream fs = new FileStream(path, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
            sw.Write(contents);
            sw.Flush();
            sw.Close();
            fs.Close();
        }
        public string TxtRead(string path)
        {
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            StreamReader sr = new StreamReader(fs, Encoding.UTF8);
            StringBuilder sb = new StringBuilder();
            while (!sr.EndOfStream)
            {
                sb.AppendLine(sr.ReadLine());
            }
            return sb.ToString();
        }

        public static DataTable ExcelToTable(string file)
        {
            DataTable dt = new DataTable();
            IWorkbook workbook;
            string fileExt = Path.GetExtension(file).ToLower();
            using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                //XSSFWorkbook 适用XLSX格式，HSSFWorkbook 适用XLS格式
                if (fileExt == ".xlsx") { workbook = new XSSFWorkbook(fs); } else if (fileExt == ".xls") { workbook = new HSSFWorkbook(fs); } else { workbook = null; }
                if (workbook == null) { return null; }
                ISheet sheet = workbook.GetSheetAt(0);

                //表头  
                IRow header = sheet.GetRow(sheet.FirstRowNum);
                List<int> columns = new List<int>();
                for (int i = 0; i < header.LastCellNum; i++)
                {
                    object obj = GetValueType(header.GetCell(i));
                    if (obj == null || obj.ToString() == string.Empty)
                    {
                        dt.Columns.Add(new DataColumn("Columns" + i.ToString()));
                    }
                    else
                        dt.Columns.Add(new DataColumn(obj.ToString()));
                    columns.Add(i);
                }
                //数据  
                for (int i = sheet.FirstRowNum + 1; i <= sheet.LastRowNum; i++)
                {
                    DataRow dr = dt.NewRow();
                    bool hasValue = false;
                    foreach (int j in columns)
                    {
                        dr[j] = GetValueType(sheet.GetRow(i).GetCell(j));
                        if (dr[j] != null && dr[j].ToString() != string.Empty)
                        {
                            hasValue = true;
                        }
                    }
                    if (hasValue)
                    {
                        dt.Rows.Add(dr);
                    }
                }
            }
            return dt;
        }
        /// <summary>
        /// 获取单元格类型
        /// </summary>
        /// <param name="cell"></param>
        /// <returns></returns>
        private static object GetValueType(ICell cell)
        {
            if (cell == null)
                return null;
            switch (cell.CellType)
            {
                case CellType.Blank: //BLANK:  
                    return null;
                case CellType.Boolean: //BOOLEAN:  
                    return cell.BooleanCellValue;
                case CellType.Numeric: //NUMERIC:  
                    return cell.NumericCellValue;
                case CellType.String: //STRING:  
                    return cell.StringCellValue;
                case CellType.Error: //ERROR:  
                    return cell.ErrorCellValue;
                case CellType.Formula: //FORMULA:  
                default:
                    return "=" + cell.CellFormula;
            }
        }
        public static int CInt(object val)
        {
            try { return Convert.ToInt32(val); }
            catch { return 0; }
        }
        public static decimal CDec(object val)
        {
            try { return Convert.ToDecimal(val); }
            catch { return 0; }
        }
        public static DateTime? CDate(object val)
        {
            try
            {
                return Convert.ToDateTime(val);
            }
            catch
            {
                try
                {
                    string strDate = DateTime.FromOADate(Convert.ToInt32(val)).ToString("d");
                    return DateTime.Parse(strDate);
                }
                catch { return null; }
            }
        }
               
        public DataTable SqlQuery(Database db, string sql)
        {            
            if (conn.State != ConnectionState.Open)
            {
                conn.ConnectionString = db.Connection.ConnectionString;
                conn.Open();
            }
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = sql;
            SqlDataAdapter adapter = new SqlDataAdapter(cmd);
            DataTable table = new DataTable();
            adapter.Fill(table);
            conn.Close();
            conn.Dispose();
            return table;
        }
        public DataTable DgvToTable(DataGridView dgv)
        {
            DataTable dt = new DataTable();

            // 列强制转换  
            for (int count = 0; count < dgv.Columns.Count; count++)
            {
                DataColumn dc = new DataColumn(dgv.Columns[count].HeaderText.ToString());
                dt.Columns.Add(dc);
            }

            // 循环行  
            for (int count = 0; count < dgv.Rows.Count; count++)
            {
                DataRow dr = dt.NewRow();
                for (int countsub = 0; countsub < dgv.Columns.Count; countsub++)
                {
                    dr[countsub] = Convert.ToString(dgv.Rows[count].Cells[countsub].Value);
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }
        public void ExportToExcel(DataTable dt, string fileName = "", string filePath = "")
        {
            if (dt == null)
            {
                return;
            }
            else
            {
                try
                {
                    var result = ExportExcel(dt, filePath, fileName);
                    if (result != null)
                    {
                        System.Diagnostics.Process.Start(result);
                    }
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        public string ExportExcel(DataTable dt, string filePath, string fileName = "")
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = GetSaveFilePath(fileName);
            }
            if (string.IsNullOrEmpty(filePath)) return null;
            try
            {
                //创建Excel文件的对象  
                NPOI.HSSF.UserModel.HSSFWorkbook book = new NPOI.HSSF.UserModel.HSSFWorkbook();
                int pageSize = 60000;
                int sheetNum = dt.Rows.Count / pageSize;
                if (dt.Rows.Count % pageSize > 0)
                    sheetNum = sheetNum + 1;

                for (int k = 1; k <= sheetNum; k++)
                {
                    NPOI.SS.UserModel.ISheet sheet1 = book.CreateSheet("Sheet" + k);
                    NPOI.SS.UserModel.IRow row1 = sheet1.CreateRow(0);
                    for (int i = 0; i < dt.Columns.Count; i++)
                    {
                        row1.CreateCell(i).SetCellValue(dt.Columns[i].ColumnName);
                    }

                    int startIndex = (k - 1) * pageSize;
                    startIndex = k == 1 ? startIndex : startIndex + 1;

                    int endIndex = k * pageSize;
                    endIndex = endIndex > dt.Rows.Count ? dt.Rows.Count : endIndex;

                    int rowStart = startIndex;
                    for (int i = 0; i < endIndex - startIndex; i++)
                    {
                        NPOI.SS.UserModel.IRow rowtemp = sheet1.CreateRow(i + 1);
                        for (int j = 0; j < dt.Columns.Count; j++)
                        {
                            rowtemp.CreateCell(j).SetCellValue(dt.Rows[rowStart][j].ToString().Trim());
                        }
                        rowStart++;
                    }
                }
                
                FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                book.Write(fs);
                fs.Dispose();
                book = null;
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return filePath;
        }

        private static string GetSaveFilePath(string fileName = "")
        {
            SaveFileDialog saveFileDig = new SaveFileDialog();
            saveFileDig.Filter = "Excel Office97-2003(*.xls)|.xls|Excel Office2007及以上(*.xlsx)|*.xlsx";
            saveFileDig.FilterIndex = 0;
            saveFileDig.OverwritePrompt = true;
            saveFileDig.InitialDirectory = "C:\\";
            saveFileDig.FileName = fileName; //默认文件名
            string filePath = null;
            if (saveFileDig.ShowDialog() == DialogResult.OK)
            {
                filePath = saveFileDig.FileName;
            }

            return filePath;
        }

        public void ExportByDGV(DataGridView dgv)
        {
            try
            {
                DataTable dt = DgvToTable(dgv);
                ExportToExcel(dt, "Temp" + DateTime.Now.ToString("yyMMddhhmmss"));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public void SetHeader(DataGridView dgv, string formName)
        {
            try
            {
                string localcfg = TxtRead(LocalCfg);
                var cfgLists = JsonConvert.DeserializeObject<List<Dto.LocalConfig>>(localcfg);
                var cfgs = cfgLists.Where(o => o.ObjName == formName + "_" + dgv.Name).ToList();
                if (cfgs != null && cfgs.Count > 0)
                {
                    int frozenIndex = 0;
                    try
                    {
                        frozenIndex = cfgs.Where(o => o.IsFrozen == true).OrderByDescending(o => o.FieldIndex).FirstOrDefault().FieldIndex;
                    }
                    catch { }
                    for (int i = 0; i < dgv.Columns.Count; i++)
                    {
                        var item = cfgs.Where(o => o.FieldIndex == i).FirstOrDefault();
                        if (item != null)
                        {
                            dgv.Columns[i].HeaderText = item.FieldDisplay;
                            dgv.Columns[i].ToolTipText = item.FieldDisplay + "(" + i.ToString() + ")";
                            dgv.Columns[i].ReadOnly = item.IsReadOnly;
                            dgv.Columns[i].Visible = !item.IsHidden;
                            dgv.Columns[i].Width = item.FieldWidth;
                            dgv.Columns[i].DisplayIndex = item.FieldDisplayIndex == 0 ? i : item.FieldDisplayIndex;
                            if (!string.IsNullOrEmpty(item.FieldFormat))
                            {
                                dgv.Columns[i].DefaultCellStyle.Format = item.FieldFormat;
                            }
                        }
                    }
                    dgv.Columns[frozenIndex].Frozen = true;
                }
            }
            catch (Exception ex){
                MessageBox.Show("系统个性化错误，请重新设置。" + ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public DataTable ListToDataTable<T>(List<T> items, string[] titArr = null, string oldRpChar = "", string newRpChar = "")
        {
            var tb = new DataTable(typeof(T).Name);

            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            if (titArr == null)
            {
                foreach (PropertyInfo prop in props)
                {
                    Type t = GetCoreType(prop.PropertyType);
                    if (!string.IsNullOrEmpty(oldRpChar) && !string.IsNullOrEmpty(newRpChar))
                    {
                        tb.Columns.Add(prop.Name.Replace(oldRpChar, newRpChar), t);
                    }
                    else
                        tb.Columns.Add(prop.Name, t);
                }
            }
            else
            {
                foreach (string tit in titArr)
                {
                    tb.Columns.Add(tit);
                }
            }

            foreach (T item in items)
            {
                var values = new object[props.Length];

                for (int i = 0; i < props.Length; i++)
                {
                    values[i] = props[i].GetValue(item, null);
                }

                tb.Rows.Add(values);
            }

            return tb;
        }
        public Type GetCoreType(Type t)
        {
            if (t != null && IsNullable(t))
            {
                if (!t.IsValueType)
                {
                    return t;
                }
                else
                {
                    return Nullable.GetUnderlyingType(t);
                }
            }
            else
            {
                return t;
            }
        }
        public bool IsNullable(Type t)
        {
            return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
        }
        public static void Info(string msg)
        {
            MessageBox.Show(msg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        public static void Warn(string msg)
        {
            MessageBox.Show(msg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
        public static void Error(string msg)
        {
            MessageBox.Show(msg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}
